﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;


namespace AudiPyme.DAL
{
    public static class Matriz_TiposActivosVulnerabilidadesFactory
    {
        //Inserta una relación tipo activo - vulnerabilidad en la base de conocimiento
        public static void InsertarMatriz_TiposActivosVulnerabilidades(Matriz_TiposActivosVulnerabilidades TipActVul)
        {
            ModeloContainer agenteBD = new ModeloContainer();
            agenteBD.AddToMatriz_TiposActivosVulnerabilidadesEstablecer(TipActVul);
            agenteBD.SaveChanges();
        }

        //Recoge una relación tipo activo - vulnerabilidad a través de los nombres de los elementos que la componen
        public static Matriz_TiposActivosVulnerabilidades BuscarMatriz_TiposActivosVulnerabilidades(String TipoActivoSeleccionado, String VulnerabilidadSeleccionada)
        {
            Matriz_TiposActivosVulnerabilidades matriz = new Matriz_TiposActivosVulnerabilidades();
            //Recogemos los Id's asociados al Tipo de Activo y Vulnerabilidad seleccionada
            int IdTipoActivoSelec = 0;
            int IdVulnerabilidadSelec = 0;
            ModeloContainer agenteBD = new ModeloContainer();
            IQueryable<int> IdTipoActivo = from TipoActivo in agenteBD.TiposActivosEstablecer
                                           where TipoActivo.TipoActivo == TipoActivoSeleccionado
                                           select TipoActivo.IdTipoActivo;
            foreach (int t in IdTipoActivo)
            {
                IdTipoActivoSelec = t;
            }
            IQueryable<int> IdVulnerabilidad = from Vulnerabilidades in agenteBD.VulnerabilidadesEstablecer
                                               where Vulnerabilidades.Vulnerabilidad == VulnerabilidadSeleccionada
                                               select Vulnerabilidades.IdVulnerabilidad;
            foreach (int v in IdVulnerabilidad)
            {
                IdVulnerabilidadSelec = v;
            }
            matriz.IdTipoActivo = IdTipoActivoSelec;
            matriz.IdVulnerabilidad = IdVulnerabilidadSelec;
            return matriz;
        }

        //Elimina una relación tipo activo - vulnerabilidad de la base de conocimiento
        public static void EliminarMatriz_TiposActivosVulnerabilidades(Matriz_TiposActivosVulnerabilidades matriz)
        {
            ModeloContainer agenteBD = new ModeloContainer();
            Matriz_TiposActivosVulnerabilidades MatrizTipActVuln = (from MTAV in agenteBD.Matriz_TiposActivosVulnerabilidadesEstablecer
                                                                    where MTAV.IdTipoActivo == matriz.IdTipoActivo &&
                                                                        MTAV.IdVulnerabilidad == matriz.IdVulnerabilidad
                                                                    select MTAV).First();
            agenteBD.Matriz_TiposActivosVulnerabilidadesEstablecer.DeleteObject(MatrizTipActVuln);
            agenteBD.SaveChanges();
        }

        //Método que recoge el número de Relaciones Tipo Activo - Vulnerabilidades disponibles en la base de conocimiento 
        public static int NumRelacTipActVuln()
        {
            ModeloContainer agenteBD = new ModeloContainer();
            int nRelac = (from RelacTipActVuln in agenteBD.Matriz_TiposActivosVulnerabilidadesEstablecer
                          where RelacTipActVuln.Actual == true
                          select RelacTipActVuln).Count();
            return nRelac;
        }

        //Método que elimina (borrado lógico) una relación del Tipo de Activo - Vulnerabilidad de la matriz de la base de conocimiento
        public static void EliminarInstanciaTipActVuln(int IdTipoActivo, int IdVulnerabilidad)
        {
            ModeloContainer agenteBD = new ModeloContainer();
            Matriz_TiposActivosVulnerabilidades RelacionEliminar
                        = (from RelMatriz in agenteBD.Matriz_TiposActivosVulnerabilidadesEstablecer
                           where RelMatriz.IdTipoActivo == IdTipoActivo &&
                                 RelMatriz.IdVulnerabilidad == IdVulnerabilidad
                           select RelMatriz).First();
            RelacionEliminar.Actual = false;
            //Ponemos todas las instancias dependientes de la relación a false
            List<Matriz_TiposActivosVulnerabilidades> LRelTipActVulnPorTipAct = new List<Matriz_TiposActivosVulnerabilidades>();
            LRelTipActVulnPorTipAct.Add(RelacionEliminar);
            List<InstanciaTiposActivosVulnerabilidades> LInstPorRelTipActVul = InstanciaTiposActivosVulnerabilidadesFactory.EliminaInstanciaPorRelacTipActVuln(LRelTipActVulnPorTipAct);
            agenteBD.SaveChanges();
        }

        //Método que hace un borrado lógico de todas las relaciones tipo activo - vulnerabilidad dependientes de una Vulnerabilidad
        public static List<Matriz_TiposActivosVulnerabilidades> EliminaRelacionesTipActVulnPorVulnerabilidad(int IdVulnerabilidad)
        {
            ModeloContainer agenteBD = new ModeloContainer();
            //Recogemos las relaciones actuales en la Base de Conocimiento
            List<Matriz_TiposActivosVulnerabilidades> LTipActAmen = new List<Matriz_TiposActivosVulnerabilidades>();
            IQueryable<Matriz_TiposActivosVulnerabilidades> RelTipActAmenCrit = from Rel in agenteBD.Matriz_TiposActivosVulnerabilidadesEstablecer
                                                                                where Rel.IdVulnerabilidad == IdVulnerabilidad && Rel.Actual == true
                                                                                select Rel;
            if (RelTipActAmenCrit.Count() != 0)
            {
                //Para cada uno actualizamos el Valor Actual a false
                foreach (Matriz_TiposActivosVulnerabilidades R in RelTipActAmenCrit)
                {
                    R.Actual = false;
                    LTipActAmen.Add(R);
                }
                agenteBD.SaveChanges();
            }
            //Si no había Relaciones dependientes devolvemos la fila vacía
            return LTipActAmen;
        }

        //Método que hace un borrado lógico de todas las relaciones tipo activo - vulnerabilidad dependientes de un tipo de activo
        internal static List<Matriz_TiposActivosVulnerabilidades> EliminaRelacionesTipActVulnPorTipoActivo(int IdTipoActivo)
        {
            ModeloContainer agenteBD = new ModeloContainer();
            //Recogemos las relaciones actuales en la Base de Conocimiento
            List<Matriz_TiposActivosVulnerabilidades> LTipActAmen = new List<Matriz_TiposActivosVulnerabilidades>();
            IQueryable<Matriz_TiposActivosVulnerabilidades> RelTipActAmenCrit = from Rel in agenteBD.Matriz_TiposActivosVulnerabilidadesEstablecer
                                                                                where Rel.IdTipoActivo == IdTipoActivo && Rel.Actual == true
                                                                                select Rel;
            if (RelTipActAmenCrit.Count() != 0)
            {
                //Para cada uno actualizamos el Valor Actual a false
                foreach (Matriz_TiposActivosVulnerabilidades R in RelTipActAmenCrit)
                {
                    R.Actual = false;
                    LTipActAmen.Add(R);
                }
                agenteBD.SaveChanges();
            }
            //Si no había Relaciones dependientes devolvemos la fila vacía
            return LTipActAmen;
        }


        //Método que restaura las relaciones tipo activo - vulnerabilidades a partir de una lista de Vulnerabilidades
        internal static List<Matriz_TiposActivosVulnerabilidades> RestauraRelacionesPorVulnerabilidad(List<int> LVulnerabilidades)
        {
            ModeloContainer agenteBD = new ModeloContainer();
            //Por cada criterio de riesgo de la lista
            //Lista de aquellas relaciones a las que se le hacen un borrado lógico
            List<Matriz_TiposActivosVulnerabilidades> LRelacionesRestauradas = new List<Matriz_TiposActivosVulnerabilidades>();
            foreach (int IdVulnerabilidad in LVulnerabilidades)
            {
                //Recogemos las Relaciones actuales de la Matriz
                IQueryable<Matriz_TiposActivosVulnerabilidades> RelacTipActVuln = from Relac in agenteBD.Matriz_TiposActivosVulnerabilidadesEstablecer
                                                                                  where Relac.IdVulnerabilidad == IdVulnerabilidad
                                                                                  select Relac;
                if (RelacTipActVuln.Count() != 0)
                {
                    //Para cada uno actualizamos el Valor Actual a True
                    foreach (Matriz_TiposActivosVulnerabilidades Relacion in RelacTipActVuln)
                    {
                        Relacion.Actual = true;
                        //Añadimos a la lista de Relaciones Eliminadas
                        LRelacionesRestauradas.Add(Relacion);
                    }
                }
            }
            agenteBD.SaveChanges();
            return LRelacionesRestauradas;
        }

        //Método que restaura las relaciones tipo activo - vulnerabilidad a partir de una lista de Tipos de Activo
        internal static List<Matriz_TiposActivosVulnerabilidades> RestauraRelacionesPorTipoActivo(List<int> LTiposActivos)
        {
            ModeloContainer agenteBD = new ModeloContainer();
            //Por cada criterio de riesgo de la lista
            //Lista de aquellas relaciones a las que se le hacen un borrado lógico
            List<Matriz_TiposActivosVulnerabilidades> LRelacionesRestauradas = new List<Matriz_TiposActivosVulnerabilidades>();
            foreach (int IdTipoActivo in LTiposActivos)
            {
                //Recogemos las Relaciones actuales de la Matriz
                IQueryable<Matriz_TiposActivosVulnerabilidades> RelacTipActVuln = from Relac in agenteBD.Matriz_TiposActivosVulnerabilidadesEstablecer
                                                                                  where Relac.IdTipoActivo == IdTipoActivo
                                                                                  select Relac;
                if (RelacTipActVuln.Count() != 0)
                {
                    //Para cada uno actualizamos el Valor Actual a True
                    foreach (Matriz_TiposActivosVulnerabilidades Relacion in RelacTipActVuln)
                    {
                        Relacion.Actual = true;
                        //Añadimos a la lista de Relaciones Eliminadas
                        LRelacionesRestauradas.Add(Relacion);
                    }
                }
            }
            agenteBD.SaveChanges();
            return LRelacionesRestauradas;
        }

        //Método que devuelve si una relación tipo activo - vulnerabilidad está en la base de datos
        public static bool EstaRelacion_TipoActivo_Vulnerabilidad(string TipoActivoSelec, string VulnerabilidadSelec)
        {
            bool esta = false;
            ModeloContainer agenteBD = new ModeloContainer();
            int IdTipoActivoSelec = TiposActivosFactory.BuscarIdTipoActivo(TipoActivoSelec);
            int IdVulnerabilidadSelec = VulnerabilidadesFactory.IdVulnerabilidad(VulnerabilidadSelec);
            IQueryable<Matriz_TiposActivosVulnerabilidades> RelacionEncontrada = from MatrTipActVuln in agenteBD.Matriz_TiposActivosVulnerabilidadesEstablecer
                                                                                 where MatrTipActVuln.IdTipoActivo == IdTipoActivoSelec && MatrTipActVuln.IdVulnerabilidad == IdVulnerabilidadSelec
                                                                                 select MatrTipActVuln;
            //Si está la relación y con el campo actual a true se devuelve un true
            if (RelacionEncontrada.Count() != 0 && RelacionEncontrada.First().Actual == true)
            {
                esta = true;
            }
            return esta;
        }

        //Método que añade a la base de conocimiento actual una relación Tipo Activo - Vulnerabilidad
        public static void Inserta_Relacion_TipoActivo_Vulnerabilidad(string TipoActivoSelec, string VulnerabilidadSelec)
        {
            ModeloContainer agenteBD = new ModeloContainer();
            Matriz_TiposActivosVulnerabilidades matriz = new Matriz_TiposActivosVulnerabilidades();
            //Recogemos los Id's asociados a la Amenaza y la Vulnerabilidad seleccionados
            int IdTipoActivoSelec = TiposActivosFactory.BuscarIdTipoActivo(TipoActivoSelec);
            int IdVulnerabSelec = VulnerabilidadesFactory.IdVulnerabilidad(VulnerabilidadSelec);
            IQueryable<Matriz_TiposActivosVulnerabilidades> Relacion = from Matriz in agenteBD.Matriz_TiposActivosVulnerabilidadesEstablecer
                                                                       where Matriz.IdTipoActivo == IdTipoActivoSelec && Matriz.IdVulnerabilidad == IdVulnerabSelec
                                                                       select Matriz;
            //Si la relacion no existe en la base de datos
            if (Relacion.Count() == 0)
            {
                //se inserta
                Matriz_TiposActivosVulnerabilidades nuevaRelacion = new Matriz_TiposActivosVulnerabilidades();
                nuevaRelacion.IdTipoActivo = IdTipoActivoSelec;
                nuevaRelacion.IdVulnerabilidad = IdVulnerabSelec;
                nuevaRelacion.Actual = true;
                InsertarMatriz_TiposActivosVulnerabilidades(nuevaRelacion);
            }
            //Si existe se actualiza su valor Actual a true
            else
            {
                Relacion.First().Actual = true;
                agenteBD.SaveChanges();
            }
        }

        //Restaura un conjunto de relaciones Tipo Activo - Vulnerabilidad en la base de conocimiento
        public static void RestauraConocimientoPorRelacion(List<Matriz_TiposActivosVulnerabilidades> LTiposActivosVulnerabilidades)
        {
            ModeloContainer agenteBD = new ModeloContainer();
            //Lista de IdsAmenazas e IdTiposAmenazas asociadas
            List<int> LIdsTiposActivos = new List<int>();
            List<int> LIdsVulnerabilidades = new List<int>();
            //Recorremos las relaciones seleccionadas 
            foreach (Matriz_TiposActivosVulnerabilidades Relacion in LTiposActivosVulnerabilidades)
            {
                Matriz_TiposActivosVulnerabilidades RelacionRestaura = (from MatrizAmenContr in agenteBD.Matriz_TiposActivosVulnerabilidadesEstablecer
                                                                        where MatrizAmenContr.IdTipoActivo == Relacion.IdTipoActivo &&
                                                                              MatrizAmenContr.IdVulnerabilidad == Relacion.IdVulnerabilidad
                                                                        select MatrizAmenContr).Single();
                RelacionRestaura.Actual = true;
                //Recogemos los Ids distintos de Tipos de Activos
                if (!LIdsTiposActivos.Contains(Relacion.IdTipoActivo))
                    LIdsTiposActivos.Add(Relacion.IdTipoActivo);
                //Recogemos los Ids distintos de Vulnerabilidades
                if (!LIdsVulnerabilidades.Contains(Relacion.IdVulnerabilidad))
                    LIdsVulnerabilidades.Add(Relacion.IdVulnerabilidad);
            }

            //Restauramos los Tipos de Activos y Vulnerabilidades recogidas a través de sus Ids
            TiposActivosFactory.RestauraTipoActivoPorRelaciones(LIdsTiposActivos);
            VulnerabilidadesFactory.RestauraVulnerabilidadPorRelaciones(LIdsVulnerabilidades);
            //Restauramos las Instancias Tipo Activo - Vulnerabilidad asociadas a esas relaciones
            InstanciaTiposActivosVulnerabilidadesFactory.RestauraInstanciaPorRelacTipActVuln(LTiposActivosVulnerabilidades);
            agenteBD.SaveChanges();
        }
    }
}
